/*
 *	OpenSource code and fragments by avocado systems, Marcus Fuhrmeister
 *
 *	Redistribution and use in source and binary forms, with or without
 *	modification, are permitted provided that the following conditions
 *	are met:
 *  
 *		* Redistribution of source code must retain the above OpenSource comment,
 *		this list of conditions and the following disclaimer.
 * 
 *		* Redistribution in binary form must reproduce the above OpenSource comment,
 *		this list of conditions and the following disclaimer in the
 *		documentation and/or other materials provided with the distribution.
 * 
 *	Neither the name of 'avocaod systems, Marcus Fuhrmeister' or the
 *	names of contributors may be used to endorse or promote products derived
 *	from this software without specific prior written permission.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
 */
package de.fuhrmeister.browserchooser.controller;

import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import java.util.Iterator;

import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;

import de.fuhrmeister.browserchooser.model.ModelFactory;
import de.fuhrmeister.util.ConfigManager;
import de.fuhrmeister.util.Tools;

/**
 * Controller class handling the view.
 * 
 * @date 20.11.2008
 * @author Marcus Fuhrmeister
 */
public class DockletPopupMenuController implements MouseListener, FocusListener {

	private static DockletPopupMenuController self;
	private JPopupMenu popup;
	private JMenuItem miNew;
	private JMenu mLanguage;
	private JMenuItem miDefaultLanguage;
	private JMenuItem miLanguageLoad;
	private JMenuItem miSettings;
	private JMenuItem miExit;

	/**
	 * Singleton pattern.
	 * 
	 * @return this
	 */
	public static synchronized DockletPopupMenuController getInstance() {
		if (self == null) {
			DockletPopupMenuController.self = new DockletPopupMenuController();
			return DockletPopupMenuController.self;
		}
		return DockletPopupMenuController.self;
	}
	
	/**
	 * Iits the popup.
	 */
	private void initPopup() {
		popup = new JPopupMenu();
		miNew = new JMenuItem();
		miNew.addMouseListener(this);
		popup.add(miNew);
		mLanguage = new JMenu();
		miDefaultLanguage = new JMenuItem();
		miDefaultLanguage.addMouseListener(this);
		mLanguage.add(miDefaultLanguage);
		mLanguage.addSeparator();
		miLanguageLoad = new JMenuItem();
		miLanguageLoad.addMouseListener(this);
		mLanguage.add(miLanguageLoad);
		popup.add(mLanguage);
		miSettings = new JMenuItem();
		miSettings.addMouseListener(this);
		popup.add(miSettings);
		popup.addSeparator();
		miExit = new JMenuItem();
		miExit.addMouseListener(this);
		popup.add(miExit);
		popup.addFocusListener(this);
	}

	/**
	 * A call to JPopupMenu.show(Component invoker, int x, int y) will fail to
	 * show the JPopupMenu if the invoker passed in is an instance of JWindow.
	 * This is a known bug (bug id : 6539458) in JAVA JDK 1.6. The bug is not
	 * existend in minor versions and it will be fixed in JDK 1.7. This method
	 * has a workaround to show the popup anyway. Therefore it test if the
	 * underlying JDK is a 1.6 version, opens a new JFrame right before showing
	 * the popup and disposes the frame afterwards.
	 * 
	 * Calls to init and update the popup if it is null and shows the popup.
	 * 
	 * @param component
	 *            the component the popup belongs to
	 * @param x
	 *            the x coordinate the popup will appear
	 * @param y
	 *            the y coordinate the popup will appear
	 * 
	 * @see URL http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539458
	 */
	public void show(final java.awt.Component component, final int x, final int y) {
		/*
		 * boolean isJDK6 =
		 * System.getProperty("java.version").startsWith("1.6"); JAVA 1.6 bug
		 * workaround final JFrame frame = new JFrame(); if (isJDK6) {
		 * frame.setUndecorated(true); frame.setSize(10, 10);
		 * frame.setLocation(-100, -100); frame.setVisible(true);
		 * frame.setVisible(false); }
		 */

		if (popup == null) {
			initPopup();
			updateLanguage();
		}
		popup.show(component, x, y);

		/*
		 * JAVA 1.6 bug workaround if (isJDK6) { frame.dispose(); }
		 */
	}

	/**
	 * Calls to updates the language in the GUI components.
	 */
	public void updateGUI() {
		this.updateLanguage();
	}

	/**
	 * Updates the language in the GUI components.
	 */
	public void updateLanguage() {
		if (popup != null) {
			miNew.setText(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_NEW)+"...");
			mLanguage.setText(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_LANGUAGE));
			mLanguage.removeAll();
			miDefaultLanguage.setText(Tools.configMng.getConfiguration(ConfigManager.LANGUAGE_DEFAULT));
			miDefaultLanguage.setActionCommand(ConfigManager.LANGUAGE);
			if (miDefaultLanguage.getText().equalsIgnoreCase(Tools.configMng.getPreference(ConfigManager.LANGUAGE))) {
				miDefaultLanguage.setEnabled(false);
			} else {
				miDefaultLanguage.setEnabled(true);
			}
			mLanguage.add(miDefaultLanguage);
			final Iterator<String> i = Tools.configMng.getInstalledLanguages();
			while (i.hasNext()) {
				final JMenuItem miLanguage = new JMenuItem(i.next());
				if (miLanguage.getText().equalsIgnoreCase(Tools.configMng.getPreference(ConfigManager.LANGUAGE))) {
					miLanguage.setEnabled(false);
				} else {
					miLanguage.setEnabled(true);
				}
				miLanguage.setActionCommand(ConfigManager.LANGUAGE);
				miLanguage.addMouseListener(this);
				mLanguage.add(miLanguage);
			}
			miLanguageLoad.setText(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_LANGUAGELOAD)+"...");
			mLanguage.add(miLanguageLoad);
			miSettings.setText(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_SETTINGS)+"...");
			miExit.setText(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_EXIT));
		}
	}

	public void mouseClicked(final MouseEvent e) {
	}

	public void mouseEntered(final MouseEvent me) {
	}

	public void mouseExited(final MouseEvent me) {
	}

	public void mousePressed(final MouseEvent e) {
	}

	/**
	 * Menu items mouse event method.
	 * Calls to load or update the language.
	 * Calls to create a new browser.
	 * Calls to show the settings dialog.
	 * Calls to exit the application.
	 * 
	 * @param me the mouse event
	 */
	public void mouseReleased(final MouseEvent me) {
		if (me.getSource() instanceof JPopupMenu) {
			return; // avoids ClassCastExceptions
		}
		if (me.getSource() instanceof JMenuItem) {
			final JMenuItem mi = (JMenuItem) me.getSource();
			if (mi.isEnabled()) {
				if (mi.getText().startsWith(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_NEW))) {
					SettingsController.getInstance().show(ModelFactory.getBrowserModelCount() + 1);
				}
				if (mi.getText().startsWith(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_LANGUAGELOAD))) {
					Controller.getInstance().loadLanguage();
				}
				if (mi.getText().startsWith(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_SETTINGS))) {
					SettingsController.getInstance().show();
				}
				if (mi.getText().startsWith(Tools.configMng.getStringFor(ConfigManager.STRING_MENUITEM_EXIT))) {
					Controller.getInstance().exit();
				}
				if (mi.getActionCommand().equalsIgnoreCase(ConfigManager.LANGUAGE)) {
					Controller.getInstance().updateLanguage(mi.getText());
				}
			}
			popup = null;
		}
	}

	/**
	 * Closes the popup.
	 */
	public void close() {
		if (popup != null) {
			popup.setVisible(false);
			popup = null;
		}
	}

	public void focusGained(FocusEvent e) {
	}

	/**
	 * Closes the popup when it looses the focus.
	 */
	public void focusLost(FocusEvent e) {
		this.close();
	}
}
